package com.ym.core.rabbit;

import com.ym.core.config.ConfigCenterProperties;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.CustomExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;

/**
 * RabbitMQConfig 配置
 *
 * @author: 李涛
 * @version: 2019年05月07日 14:47
 */
@Configuration
public class RabbitMQConfig {


	//----------------------------常量定义-----------------------
	private static final String POINT = ".";
	private static final String NORMAL = "nml";
	private static final String DELAY = "dly";
	private static final String QUEUE = "que";

	//----------------------------交换器定义----------------------------
	/**
	 * 普通交换器名字
	 */
	public static String NORMAL_EXCHANGE = "";

	/**
	 * 死信交换器名字
	 */
	public static String DEAD_EXCHANGE = "";

	/**
	 * 延时交换器名字
	 */
	public static String DELAY_EXCHANGE = "";
	//-------------------------队列定义--------------------------

	/**
	 * 普通队列
	 */
	public static String NORMAL_QUEUE = null;

	/**
	 * 延时队列存放任务
	 */
	public static String DELAY_QUEUE = null;

	/**
	 * 普通死信队列
	 */
	public static String DEAD_NORMAL_QUEUE = null;

	/**
	 * 延时死信队列
	 */
	public static String DEAD_DELAY_QUEUE = null;


	@Autowired
	private ConfigCenterProperties configCenterProperties;

	@Bean
	public RabbitTemplate rabbitTemplate(CachingConnectionFactory rabbitListenerContainerFactory) {
		RabbitTemplate rabbitTemplate = new RabbitTemplate(rabbitListenerContainerFactory);
		rabbitTemplate.setUsePublisherConnection(true);
		rabbitTemplate.setChannelTransacted(true);
		return rabbitTemplate;
	}

	@PostConstruct
	public void init() {
		RabbitRuleConfig rabbitRuleConfig = configCenterProperties.getRabbitRuleConfig();
		NORMAL_EXCHANGE = rabbitRuleConfig.getNormalExchange() + POINT + rabbitRuleConfig.getSystemMark();
		DEAD_EXCHANGE = rabbitRuleConfig.getDeadExchange() + POINT + rabbitRuleConfig.getSystemMark();
		DELAY_EXCHANGE = rabbitRuleConfig.getDelayExchange() + POINT + rabbitRuleConfig.getSystemMark();
		NORMAL_QUEUE = rabbitRuleConfig.getNormalExchange() + POINT + QUEUE + POINT + rabbitRuleConfig.getSystemMark();
		DELAY_QUEUE = rabbitRuleConfig.getDelayExchange() + POINT + QUEUE + POINT + rabbitRuleConfig.getSystemMark();
		DEAD_NORMAL_QUEUE = rabbitRuleConfig.getDeadExchange() + POINT + QUEUE + POINT + NORMAL + POINT + rabbitRuleConfig.getSystemMark();
		DEAD_DELAY_QUEUE = rabbitRuleConfig.getDeadExchange() + POINT + QUEUE + POINT + DELAY + POINT + rabbitRuleConfig.getSystemMark();
	}


	@Bean
	public RabbitListenerContainerFactory<?> rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
		SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
		factory.setConnectionFactory(connectionFactory);
		factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
		//factory.setMessageConverter(new Jackson2JsonMessageConverter());
		factory.setChannelTransacted(true);
		return factory;
	}

/*	@Bean
	public RabbitListenerContainerFactory<?> rabbitListenerContainerFactory2(ConnectionFactory connectionFactory) {
		SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
		factory.setConnectionFactory(connectionFactory);
		factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
		factory.setMessageConverter(new SerializerMessageConverter());
		factory.setChannelTransacted(true);
		return factory;
	}*/

	//------------------------------交换器声明start---------------------------

	@Bean
	public TopicExchange normalExchange() {
		return new TopicExchange(NORMAL_EXCHANGE);
	}

	@Bean
	public TopicExchange deadExchange() {
		return new TopicExchange(DEAD_EXCHANGE);
	}

	@Bean
	public CustomExchange delayExchange() {
		Map<String, Object> args = new HashMap<>();
		args.put("x-delayed-type", "topic");
		return new CustomExchange(DELAY_EXCHANGE, "x-delayed-message", true, false, args);
	}

	//------------------------------交换器声明end---------------------------

	//-------------------------------队列start---------------------------------

	@Bean
	public Queue deadNormalQueue() {
		return new Queue(DEAD_NORMAL_QUEUE);
	}

	@Bean
	public Queue deadDelayQueue() {
		return new Queue(DEAD_DELAY_QUEUE);
	}

	@Bean
	public Queue normalQueue() {
		Map<String, Object> params = new HashMap<>();
		params.put("x-dead-letter-exchange", DEAD_EXCHANGE);
		params.put("x-dead-letter-routing-key", DEAD_NORMAL_QUEUE);
		return new Queue(NORMAL_QUEUE, true, false, false, params);
	}

	@Bean
	public Queue delayQueue() {
		Map<String, Object> params = new HashMap<>();
		params.put("x-dead-letter-exchange", DEAD_EXCHANGE);
		params.put("x-dead-letter-routing-key", DEAD_DELAY_QUEUE);
		return new Queue(DELAY_QUEUE, true, false, false, params);
	}
	//-------------------------------队列end---------------------------------


	//-------------------------------绑定start---------------------------------

	@Bean
	public Binding bindingNormalExchange(Queue normalQueue, TopicExchange normalExchange) {
		return BindingBuilder.bind(normalQueue).to(normalExchange).with(NORMAL_QUEUE);
	}

	@Bean
	public Binding bindingNormalDeadExchange(Queue deadNormalQueue, TopicExchange deadExchange) {
		return BindingBuilder.bind(deadNormalQueue).to(deadExchange).with(DEAD_NORMAL_QUEUE);
	}

	@Bean
	public Binding bindingDelayExchange(Queue delayQueue, CustomExchange delayExchange) {
		return BindingBuilder.bind(delayQueue).to(delayExchange).with(DELAY_QUEUE).noargs();
	}

	@Bean
	public Binding bindingDelayDeadExchange(Queue deadDelayQueue, TopicExchange deadExchange) {
		return BindingBuilder.bind(deadDelayQueue).to(deadExchange).with(DEAD_DELAY_QUEUE);
	}

	//-----------------------------------------绑定end------------------------------------------

}
